package wap.rockvilletech.portal;

import java.awt.image.BufferedImage;
import java.awt.image.renderable.ParameterBlock;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;

import javax.imageio.ImageIO;
import javax.media.jai.Interpolation;
import javax.media.jai.JAI;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sourceforge.wurfl.core.Device;
import net.sourceforge.wurfl.core.WURFLHolder;
import net.sourceforge.wurfl.core.WURFLManager;

import org.apache.log4j.Logger;
import org.clapper.util.misc.MIMETypeUtil;

import wap.rockvilletech.util.imaging.ProcessWallpaper;

/**
 *
 * @author tazzix
 * @version
 */
@SuppressWarnings("serial")
public class DownloadHelper extends HttpServlet {

    private static final Logger log = Logger.getLogger(DownloadHelper.class);

    /** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        ArrayList arrDetails = new ArrayList();
        ArrayList arrARatios = new ArrayList();

        String msisdn = "";
        String brand = "";
        String model = "";

        String Contentid = "";
        String Contentname = "";
        String Categoryid = "";
        String Categoryname = "";
        String OriginalFile = "";
        String price = "";
        String St = "";
        String Providerid = "";
        String ContentImage = "";
        String Format = "";
        String Width = "";
        String Height = "";
        String AspectRatio = "";
        String SingerOrFilm = "";
        String Serviceurl = "";
        String Parameters = "";
        String jspf = "";
        String OrderSequence = "";
        String InsertionTime = "";
        String CategoryType = "";
        String Description = "";
        String Samplefile = "";
        String Providercontentid = "";
        String gtseqid = "";
        String Contentfile = "";
        String originalPath = "";
        String logId = "";
        String ip = "";

        String wd = "0";
        String ht = "0";
        String fullPath = "";
        int contentLength = 0;
        float aratio = 0;
        int h = 0;
        int w = 0;
        int iContentManipulation = 0;

        boolean isJAR = false;
        boolean isJAD = false;
        boolean status = true;

        // Variables used to process dynamic Wallpapers
        boolean dynamicWallpaper = false;
        String point1 = "", point2 = "", bias = "", fillColor = "";
        try {
        	
            WURFLHolder wurflHolder = (WURFLHolder) getServletContext().getAttribute("net.sourceforge.wurfl.core.WURFLHolder");
        	WURFLManager wurfl = wurflHolder.getWURFLManager();
        	Device device = wurfl.getDeviceForRequest(request);    		
        	
            WapPortalBean wpb = new WapPortalBean(device);
        	
            String context=getServletContext().getContextPath();
            msisdn = request.getParameter("msisdn") != null ? request.getParameter("msisdn") : "";
            logId = request.getParameter("logid") != null ? request.getParameter("logid") : "";
            wd = request.getParameter("w") != null ? request.getParameter("w") : "0";
            ht = request.getParameter("h") != null ? request.getParameter("h") : "0";
            gtseqid = request.getParameter("g") != null ? request.getParameter("g") : "0";
            String filename = request.getParameter("fn") != null ? request.getParameter("fn") : "";
            brand = request.getParameter("brand") != null ? request.getParameter("brand") : "";
            model = request.getParameter("model") != null ? request.getParameter("model") : "";
            ip = request.getRemoteHost();
            String seqid = null;
            if(!"".equals(filename)){
            	if ((filename.indexOf(".jar") != -1)) {
                    isJAR = true;
                } else if ((filename.indexOf(".jad") != -1)) {
                    isJAD = true;
                }
                seqid = filename.substring(0, filename.indexOf("."));
            }
                        
            if (isJAR) {
                seqid = filename.substring(filename.indexOf("seqid_") + 6);
                seqid = seqid.substring(0, seqid.indexOf("/"));
                filename=filename.substring(filename.lastIndexOf("/")+1);
                
            }
            log.info("seqid = " + seqid + ", msisdn = " + msisdn + ", width = " + wd + ", height = " + ht + ", filename = " + filename);
            arrDetails = wpb.getContentData(seqid);
            //--log.info("arr size()===:" + arrDetails.size());

            if (arrDetails.size() >= 24) {
                Contentid = arrDetails.get(1).toString();
                Contentname = arrDetails.get(2).toString();
                Categoryid = arrDetails.get(3).toString();
                Categoryname = arrDetails.get(4).toString();
                OriginalFile = arrDetails.get(5).toString();
                price = arrDetails.get(6).toString();
                St = "0"; //arrDetails.get(7).toString(); - we do not want to store the content status, but the downloaded status
                Providerid = arrDetails.get(8).toString();
                ContentImage = arrDetails.get(9).toString();
                Format = arrDetails.get(10).toString();
                Width = arrDetails.get(11).toString();
                Height = arrDetails.get(12).toString();
                AspectRatio = arrDetails.get(13).toString();
                SingerOrFilm = arrDetails.get(14).toString();
                Serviceurl = arrDetails.get(15).toString();
                Parameters = arrDetails.get(16).toString();
                jspf = arrDetails.get(17).toString();
                OrderSequence = arrDetails.get(18).toString();
                InsertionTime = arrDetails.get(19).toString();
                CategoryType = arrDetails.get(20).toString();
                Description = arrDetails.get(21).toString();
                Samplefile = arrDetails.get(22).toString();
                Providercontentid = arrDetails.get(23).toString();

                //check for previous downloads            
                String msg = null;
                log.debug("Check download status of CategoryType=" + CategoryType);
                int status_dload = wpb.getDownloadedStatus(Contentid, CategoryType, msisdn);
                if (status_dload == -2) {
                    msg = "Invalid Request, Required parameters are missing!";
                } else if (status_dload == -1) {
                    msg = "Invalid Request, Content Not Exists or is Removed!";
                } else if (status_dload > 1) {
                    msg = "Dear User, You can download only one content item per request!";
                }

                if (msg != null) {
                    response.setContentType("text/plain");
                    PrintWriter out = response.getWriter();
                    out.println(msg);
                    out.close();
                    log.info("[" + msisdn + "] Error:" + msg + ", returning here..");
                    return;
                }

                // Parameters for Dynamic Wallpeper Resizing Module
                try {
//                  log.debug("Start - ");
                    point1 = arrDetails.get(24).toString().trim();
                    point2 = arrDetails.get(25).toString().trim();
                    bias = arrDetails.get(26).toString().trim();
                    fillColor = arrDetails.get(27).toString().trim();

                    if (point1 != null && point2 != null
                            && !point1.equalsIgnoreCase("NULL") && !point1.equalsIgnoreCase("<NULL>")
                            && !point2.equalsIgnoreCase("NULL") && !point2.equalsIgnoreCase("<NULL>")
                            && point1.length() > 1 && point2.length() > 1
                            && CategoryType.equalsIgnoreCase("WALLPAPERS")) {
                        dynamicWallpaper = true;
                    }
                } catch (Exception e) {
                    dynamicWallpaper = false;
                    log.error("Error getting wallpaper ", e);
                }
            }

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            originalPath = wpb.getOriginalPath(Categoryid);
            fullPath = originalPath + OriginalFile;
            
            // New Logic to implement Dynamic Resizing of Wallpapers
            if (dynamicWallpaper) {                
                BufferedImage image = null;
                try {
                	image = ProcessWallpaper.generateWallpaper(fullPath, point1, point2, bias, fillColor, wd, ht);
                    ImageIO.write(image, "jpeg", baos);
                    response.setContentType("image/jpeg");
                    try {image.flush();}catch(Exception e){}
                    log.info("dynamic image("+fullPath+") processed and written on baos");
                } catch (Exception e) {
                    status = false;
                	log.warn("Error writing dynamic image("+fullPath+") to ImageIO!"); 
                } finally {
                	image = null;
                }
            }
            else {
                if (CategoryType.equalsIgnoreCase("GAMES") || CategoryType.equalsIgnoreCase("Network Games") || CategoryType.equalsIgnoreCase("THEMES")) {
                    // Modifications for JAR by USMAN
                    if (isJAR) {
                        OriginalFile = "/" + filename;
                        originalPath = SystemProperty.getProperty("JAR_basePath");
                    } 
                    else {
                        if (gtseqid.contains("/")) {
                            gtseqid = gtseqid.substring(0, gtseqid.indexOf("/"));
                        }
                        Contentfile = wpb.getContentFile(gtseqid);
                        OriginalFile = Contentfile;
                    }
                    fullPath = originalPath + OriginalFile;
                    log.info("fullPath="+fullPath+", originalPath="+originalPath+", OriginalFile="+OriginalFile);
                } 
                else if (CategoryType.equalsIgnoreCase("WALLPAPERS")) {
                        iContentManipulation = 1;
                        arrARatios = wpb.getAspectRatios(Contentid);
                }
                else if ( CategoryType.equalsIgnoreCase("ANIMATED")) {
                        iContentManipulation = 2;
                        arrARatios = wpb.getAspectRatios(Contentid);
                }
                // Modifications for JAR by USMAN
                if (!isJAR) {
                    h = Integer.parseInt(ht);
                    w = Integer.parseInt(wd);

                    aratio = (float) w / (float) h;
                }

                if (iContentManipulation != 0) {
                    HashMap hm = new HashMap();
                    ArrayList alist = new ArrayList();
                    for (int i = 0; i < arrARatios.size(); i += 3) {
                        String name = arrARatios.get(i + 2).toString();
                        String orgfile = arrARatios.get(i + 1).toString();
                        //name = name.substring( 0, name.lastIndexOf(".") );
                        float fratio = Float.parseFloat(name);
                        fratio = Math.abs(aratio - fratio);
                        //log.debug("FS:"+name+":"+fratio);
                        hm.put(fratio, orgfile);
                        alist.add(fratio);
                    }
                    java.util.Collections.sort(alist);
                    fullPath = originalPath + hm.get(alist.get(0));
                    fullPath = fullPath.trim().replace("\n", "");
                }

                File cntFile = new File(fullPath);

                if (iContentManipulation == 1) {
                	BufferedImage image = null;
                    try {
                        image = ImageIO.read(cntFile);

                        ParameterBlock pb = new ParameterBlock();
                        pb.addSource(image);
                        pb.add(((float) w / image.getWidth()));
                        pb.add(((float) h / image.getHeight()));
                        pb.add(0.0F);
                        pb.add(0.0F);
                        pb.add(Interpolation.getInstance(Interpolation.INTERP_BILINEAR));

                        image = JAI.create("scale", pb).getAsBufferedImage();
                        ImageIO.write(image, "jpeg", baos);
                        response.setContentType("image/jpeg");        
                        try {image.flush();}catch(Exception e){}
                        log.debug("image("+fullPath+") processed and written on baos");
                    } catch(Exception e) {
                        status = false;
                        log.warn("Error writing image("+fullPath+") to ImageIO!"); 
                    } finally {
                    	image = null;
                    }
                } 
                else {
                    if ("mp3".equals(Format)) {
                        response.setContentType("audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3");
                    } else if ("3gp".equals(Format)) {
                        response.setContentType("video/3gpp");
                    } else {
                        response.setContentType(MIMETypeUtil.MIMETypeForFile(cntFile));
                    }
                    FileInputStream fis = new FileInputStream( cntFile );
                    BufferedInputStream bis = new BufferedInputStream(fis);
                    contentLength = Integer.parseInt(String.valueOf(cntFile.length()));
                    int length = 0;
                    byte [] bytes = new byte[contentLength];
                    while( (length = bis.read(bytes)) != -1 ) {
                        baos.write( bytes, 0, length );
                    }
                    bis.close();
                    fis.close();
                    bytes = null;
                }
            } // New Logic for Dynamic Resizing - Else Block Ends Here
            
            if(isJAD && baos.size() > 0) {
				String jadBytes = new String(baos.toByteArray());
				String jarURL = jadBytes.substring(jadBytes.indexOf("MIDlet-Jar-URL:") + 15, jadBytes.indexOf(".jar") + 4).trim();
				String jarFileName = jarURL.substring(jarURL.lastIndexOf("/")+1);

                jarFileName = "http://wap.ufone.com"+context+"/downloader?msisdn=" + msisdn + "&g=" + gtseqid + "&fn=seqid_" + seqid + "/" + jarFileName;
				log.debug("["+seqid+":"+msisdn+"] jar url: "+jarFileName);
				jadBytes = jadBytes.replaceAll("[Mn][Ii][Dd][Ll][Ee][Tt]-[Jj][Aa][Rr]-[Uu][Rr][Ll](.|\\s)*?(\\.jar)", "MIDlet-Jar-URL: " + jarFileName);
				baos = new ByteArrayOutputStream();
				baos.write(jadBytes.getBytes());
            }
            
            response.addHeader("Content-Disposition", "attachment; filename=" +  Contentname.replaceAll(" ", "_")+"."+Format);
            contentLength = baos.size();
            
            if("keep-alive".equalsIgnoreCase(request.getHeader("Connection"))) {
            	response.setContentLength(contentLength);
            }    
            
            try {
            	baos.writeTo(response.getOutputStream());
            } catch (Exception e) {
                status = false;
                log.warn("Error writing bytes to outputstream, file="+fullPath+", contentLength:"+contentLength);
            } finally {
            	baos = null;
            }
        
            if (status) {                
                if (!isJAD) {                    
                    int x = wpb.updDownload(Contentid, msisdn);                    
                    wpb.recordDownload(Contentid);
                    wpb.setContentDownloadStatus(logId, price, ip, brand, model);
                    log.debug(" ----> Download complete, status update="+x);
                    //content_id, category_type, query_string, price, ip, brand, model
                    //contentdownload/price_5
//                    String str_charging_url="http://wap.ufone.com"+context+"/contentdownload/price_"+price+"?price="+price+"&cid="+Contentid+"&ctype="+CategoryType+"&brand="+URLEncoder.encode(brand,"UTF-8")+"&model="+URLEncoder.encode(model,"UTF-8");
//                    String charging_responce = wpb.getURLResponse(str_charging_url);
//                    log.info("Charging URL ("+str_charging_url+") Responce="+charging_responce+", Update Download Status="+x);
                }
                wpb = null;
            }

        } catch (Exception exc) {
            log.error("Error processing download content: ", exc);
            status=false;
        }        
    }

    /** Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** Returns a short description of the servlet.
     */
    public String getServletInfo() {
        return "Short description";
    }
}
